﻿using System;
using System.Configuration;
using System.IO;
using System.Linq;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using System.Collections.Generic;
using MongoDB.Bson.IO;

namespace zeroone.Madrona.Models
{
    public class Recordset
    {
        #region Properties
        public string CollectionName { get; set; }

        private static string mongoConnectionString
        {
            get
            {
                return ConfigurationManager.AppSettings["MongoDBConnectionString"];
            }
        }
        private static string mongoDatabaseName
        {
            get
            {
                return ConfigurationManager.AppSettings["MongoDBDatabaseName"];
            }
        }

        private MongoServer mongoServer;
        public MongoServer MongoServer
        {
            get
            {
                if (mongoServer == null)
                    try
                    {
                        mongoServer = MongoServer.Create(mongoConnectionString);
                    }
                    catch (Exception ex)
                    {
                        throw new MongoConnectionException(string.Format("unable to connect to database with connection string {0}", mongoConnectionString), ex);
                    }
                return mongoServer;
            }
        }

        private MongoDatabase database;
        public MongoDatabase Database
        {
            get
            {
                if (database == null)
                {
                    var dbNames = MongoServer.GetDatabaseNames();

                    if (dbNames.Contains<string>(mongoDatabaseName))
                    {
                        database = MongoServer.GetDatabase(mongoDatabaseName);
                    }
                    else
                        throw new FileNotFoundException(string.Format(@"Database does not exist with the name: ""{0}""", mongoDatabaseName));
                }
                return database;
            }
        }

        private MongoCollection<BsonDocument> collection;
        public MongoCollection<BsonDocument> Collection
        {
            get
            {
                if (collection == null)
                {
                    var collectionNames = Database.GetCollectionNames();
                    if (collectionNames.Contains<string>(CollectionName))
                    {
                        collection = Database.GetCollection(CollectionName);
                    }
                    else
                        throw new FileNotFoundException(string.Format(@"Collection does not exist with the name: ""{0}""", CollectionName));
                }
                return collection;
            }
        }

        public JsonWriterSettings JsonSettings
        {
            get
            {
                return new JsonWriterSettings { OutputMode = JsonOutputMode.Strict };
            }
        }

        #endregion Properties

        #region CTOR
        public Recordset(string collectionName)
        {
            this.CollectionName = collectionName;
        }
        #endregion CTOR

        #region CRUD
        public string GetRecordset()
        {
            return Collection.FindAll().ToJson(JsonSettings);
        }

        public string GetRecordById(string id)
        {
            var query = Query.EQ("_id", new ObjectId(id));
            //var query = Query.EQ("firstName", "Jonathan");
            var results = Collection.Find(query).ToList();
            if (results.Count == 0)
                return string.Empty;
            if (results.Count > 1)
                throw new IndexOutOfRangeException(string.Format(@"More than one record returned with query {0}", query.ToJson(JsonSettings)));

            return results.First().ToJson(JsonSettings);
        }

        public string CreateRecord(Dictionary<string, object> values)
        {
            var data = new BsonDocument(values);
            var x = Collection.Insert(data, SafeMode.True);
            var d = x.Response;
            var x2 = new { id = "can id go here?" };
            return x2.ToJson(JsonSettings);
        }

        public string DeleteRecordById(string id)
        {
            var query = Query.EQ("_id", new ObjectId(id));
            //var query = Query.EQ("firstName", "John");
            var results = Collection.Find(query).ToList();
            if (results.Count == 0)
                return string.Empty;
            if (results.Count > 1)
                throw new IndexOutOfRangeException(string.Format(@"More than one record returned with query {0}", query.ToJson(JsonSettings)));

            var x = Collection.Remove(query, SafeMode.True);
            return id;
        }


        #endregion CRUD
    }
}